package com.ifun;

import lombok.Data;
import lombok.extern.log4j.Log4j;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据库连接操作类
 * */
@Data
@Log4j
public class OrignalBaseDao {
	//静态块  该类一被调用 即首先执行的代码块  生命周期直到程序终止
	//并且只执行一次 做到初始化作用

	private String driverName;
	/**
	 * 用户名
	 */
	public String username;
	/**
	 * 密码
	 */
	public String password;
	/**
	 * 连接地址
	 */
	public String url;

	public OrignalBaseDao( String driverName,   String url,   String username,   String password) {
		this.driverName = driverName;
		this.username = username;
		this.password = password;
		this.url = url;

		try {
			//加载驱动
			Class.forName(driverName);
		} catch (ClassNotFoundException e) {
			log.error("",e);
		}
	}

	/**
	 *获取连接
	 * @return 一个执行对象
	 */
	public Connection getConnection(){
		try{
			Connection con=DriverManager.getConnection(url,username,password);
			return con;
		}
		catch(Exception ee){
			ee.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 关闭数据库连接
	 * @param state 要关闭的执行对象
	 * @param set 要关闭的结果集对象
	 */
	public void close(Statement state,ResultSet set){
		try{
			if(set!=null){//先关闭结果集
				set.close();
				}
			if(state!=null){//然后再关闭执行对象  最后关闭连接对象
				//通过state中的getConnection()方法获得产生state对象的连接
				Connection con=state.getConnection();
				state.close();
				con.close();
			}
		}catch(Exception ee){ee.printStackTrace();}
	}

	/**
	 * 为prestatement设置值
	 * @return
	 */
	private PreparedStatement setPreStatement(String sql,Object[] objs,Connection con){
		PreparedStatement ps=null;
		try {
			ps=con.prepareStatement(sql);
			if(objs!=null && objs.length>0){
				for (int i = 0; i < objs.length; i++) {
					if(objs[i]==null)objs[i]="";
					try {
						ps.setObject(i+1, objs[i]);
					} catch (Exception e) {
						e.printStackTrace();
						return null;
					}
				}
			}
			return ps;
		} catch (Exception e) {
		}
		return null;
	}

	public ResultSet queryDB(Connection connection,String sql,Object[] obj){
		PreparedStatement ps=null;
		ResultSet set=null;
		if(connection!=null){
			try {
				ps=setPreStatement(sql,obj, connection);
				return ps.executeQuery();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
		return set;
	}
	
	/**
	 * 获得结果
	 * @param sql 要执行查询的SQL语句
	 * @return 一个结果集
	 */
	public ResultSet queryDB(String sql,Object[] obj){
		Connection con=getConnection();
		return queryDB(con,sql,obj);
	}
	
	/**
	 * 将结果集填充到对象数组
	 * @param rs
	 */
	public Object[] fillRsToObjects(ResultSet rs){
		
		if(rs!=null){
			try {
				ResultSetMetaData rd=rs.getMetaData();
				int count=rd.getColumnCount();
				Object[] objs=new Object[count];
				for (int i = 0; i < objs.length; i++) {
					try{
						objs[i]=rs.getObject(i);
					}catch(Exception e){
						//objs[i]="";//如果失败了默认为空
					}
				}
				return objs;
				
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	/**
	 * 根据结果集返回 一个Map对象 封装 字段名:值 的形式  作用:在获取多表数据时  仍然可以将数据封装成 {键:值,键:值}
	 * @param rs
	 * @return
	 */
	public List<Map<String, String>> getMapsList(ResultSet rs,boolean closeNow) throws Exception{
		List list=new ArrayList();
		if(rs!=null){
			ResultSetMetaData rd;
			while (rs.next()){
				HashMap<String, Object> map=new HashMap<String, Object>();
				try {
					rd = rs.getMetaData();
					int count=rd.getColumnCount();
					for (int j = 1; j <= count; j++) {
						map.put(rd.getColumnName(j), rs.getObject(j));
					}
					list.add(map);
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (closeNow)
				close(null,rs);
		}
		return list;
	}

	public List<Map<String, String>> getMapsList(String sql,boolean closeNow)throws Exception{
		return getMapsList(queryDB(sql,null),closeNow);
	}

	public List<Map<String, String>> getMapsList(Connection connection,String sql,boolean closeNow)throws Exception{
		return getMapsList(queryDB(connection,sql,null),closeNow);
	}

	public int execute(String sql,Object... obj) throws Exception {
		Connection con=getConnection();
		return execute(con,sql,obj);
	}

	public int execute(Connection connection,String sql,Object... obj) throws Exception {
		PreparedStatement ps=null;
		if(connection!=null){
			try {
				ps=setPreStatement(sql,obj, connection);
				return ps.executeUpdate();
			}
			catch (Exception e) {
				throw e;
			}
		}
		return 0;
	}
}
